//
//  IAgoraRtmpSender.h
//  RtmpSender
//
//  Created by LSQ on 2020/2/12.
//  Copyright © 2020 Agora. All rights reserved.
//

#pragma once

#include <stdint.h>

#include "AgoraBase.h"

namespace agora {
namespace rtc {

enum RtmpSocketState {
  kSocketStateUnknown = 0,
  kSocketStateStartConnected = 1,    // start connection connected
  kSocketStateSending = 2,           // start (or restart) sending packet
  kSocketStateStop = 3,              // stop connection
  kSocketStateStartError = 4,        // start connection error
  kSocketStateReconnecting = 5,      // rtmp reconnecting
  kSocketStateReconnected = 6,       // rtmp reconnected
  kSocketStateReconnectTimeout = 7,  // rtmp reconnect timeout
  kSocketStateBadName = 8,           // rtmp badname
};

struct RtmpSenderStatisticsInfo {
  uint64_t video_width;
  uint64_t video_height;
  uint64_t video_bitrate;
  uint64_t audio_bitrate;
  uint64_t video_frame_rate;

  uint64_t push_video_frame_cnt;
  uint64_t push_audio_frame_cnt;
  uint64_t skip_video_pframe_cnt;
  uint64_t skip_video_iframe_cnt;
  uint64_t pop_video_frame_cnt;
  uint64_t pop_audio_frame_cnt;
};

struct RtmpConfig {
  int video_width;
  int video_height;
  int video_bitrate;
  int framerate;
  int audio_sample_rate_hz;
  int audio_bytes_per_sample;
  int audio_numbder_of_channels;
  unsigned int gop_ms;

  RtmpConfig()
      : video_width(0),
        video_height(0),
        video_bitrate(0),
        framerate(0),
        audio_sample_rate_hz(0),
        audio_bytes_per_sample(0),
        gop_ms(2000),
        audio_numbder_of_channels(0) {}
};

enum RtmpStreamingBufferState {
  kStreamingBufferNone = 0,
  kStreamingBufferIncreasing = 1,  // The buffer is in bad increasing state
  kStreamingBufferDeclining = 2,   // The buffer is in good declining state
};

class IRtmpSenderObserver {
 public:
  virtual void OnRtmpSocketStateChanged(RtmpSocketState status) = 0;
  virtual void OnRtmpSenderStatisticsInfo(RtmpSenderStatisticsInfo statistics_info) = 0;
  virtual void OnRtmpStreamingBufferState(RtmpStreamingBufferState status) = 0;
  virtual ~IRtmpSenderObserver() {}
};

class IAgoraRtmpSender {
 public:
  virtual int Initialize(const RtmpConfig& rtmp_config) = 0;
  virtual int Start(const char* url) = 0;
  virtual void Stop() = 0;
  virtual void Release() = 0;
  virtual int SendAudioFrame(const uint8_t* data, size_t size, int64_t pts_ms) = 0;
  virtual int SendVideoFrame(const uint8_t* data, size_t size, int64_t pts_ms, bool is_key) = 0;
  virtual int WriteFlvFile(const char* filename, bool is_have_audio = true,
                           bool is_have_video = true) = 0;
  virtual void WriteFlvClose() = 0;
  virtual int RegisterRtmpSenderObserver(IRtmpSenderObserver* observer) = 0;
  virtual int UnregisterRtmpSenderObserver(IRtmpSenderObserver* observer) = 0;

 protected:
  virtual ~IAgoraRtmpSender() {}
};

struct RtmpMediaFrame {
  uint8_t* data;
  size_t size;
  uint32_t pts_ms;
  bool is_key_frame;
  bool is_video_frame;
  bool operator<(const RtmpMediaFrame& t) const { return t.pts_ms > this->pts_ms; }
  RtmpMediaFrame()
      : data(nullptr), size(0), pts_ms(0), is_key_frame(false), is_video_frame(false) {}
  virtual ~RtmpMediaFrame() {}
};

}  // namespace rtc
}  // namespace agora
